package com.xcity.game.employee.config.impl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

import com.xcity.db.entity.Employee;
import com.xcity.db.entity.Player;
import com.xcity.game.common.Cause;
import com.xcity.game.common.PlayerPool;
import com.xcity.game.employee.EmployeeService;
import com.xcity.game.employee.config.AbstractConfigure;
import com.xcity.game.employee.config.Configure;
import com.xcity.game.employee.config.EmployeeServiceConfigure;
import com.xcity.game.employee.template.EmployeeProduceV2Template;
import com.xcity.game.employee.template.EmployeeRecruitFixedDropTemplate;
import com.xcity.game.employee.template.EmployeeRecruiteShowTemplate;
import com.xcity.game.employee.template.EmployeeTemplate;
import com.xcity.game.item.DropGroupTemplate;
import com.xcity.game.item.ItemEffect;
import com.xcity.game.item.ItemTemplate;
import com.xcity.game.item.drop.Drop;
import com.xcity.game.item.drop.DropGroup;
import com.xcity.game.item.drop.listener.ItemDropListener;
import com.xcity.game.item.listener.BagListener;

import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;
import naga.x.App;
import naga.x.common.Interval;
import naga.x.game.template.TemplateService;
import naga.x.util.CommonUtils;

/**
 * 员工招聘配置
 * @author yang.li
 *
 */
public class EmployeeRecruitConfigure extends AbstractConfigure {
	
	protected Random random;
	@Deprecated
	protected List<Configuration>[] configs; // 钻石、高级、普通
	protected List<RecruitDropItem>[] itemConfigs;
	protected TIntObjectMap<EmployeeRecruitFixedDropTemplate> fixedDrops; // 招聘固定掉落
	protected List<Integer> countLimitList;//次数限制index2count
	
	protected List<Integer> showGoldProduce;//现金产出物品展示
	protected List<Integer> showStoneProduce;//钻石产出物品展示
	protected List<Integer> showBookProcue;//招聘书产出物品展示
	
	protected List<Integer> stoneFixedDropList = new ArrayList<Integer>();//固定掉落数组 index2次数

	// 招聘方式
	public static byte RECRUIT_TYPE_STONE_ONE = 0;
	public static byte RECRUIT_TYPE_STONE_TEN = 1;
	public static byte RECRUIT_TYPE_MONEY_ONE = 2;
	public static byte RECRUIT_TYPE_MONEY_TEN = 3;
	public static byte RECRUIT_TYPE_MONEY_HUNDRED = 4;
	public static byte RECRUIT_TYPE_SENIOR = 5;
	public static byte RECRUIT_TYPE_GENERAL = 6;
	
	public static int PROTECT_FROM_GOODLUCK_MAX_COUNT = 2;//钻石10抽防脸红 上限次数(脸红X次以后走脸黑掉落组)
	public static int PROTECT_FROM_GOODLUCK_ITEMID_BEGIN = 80200;//判断脸红掉落物品ID下限(不包含)
	public static int PROTECT_FROM_GOODLUCK_ITEMID_END = 90000;//判断脸红掉落物品ID下限(不包含)
	
	//掉落方式 不再是招聘方式
	public enum Type {
		STONE_FREE(0, PlayerPool.PROPERTY_EMPLOYEE_STONE_RECRUIT_COUNT),//免费
		STONE_ONE(0, PlayerPool.PROPERTY_EMPLOYEE_STONE_RECRUIT_COUNT),//抽一次
		STONE_TEN(0, PlayerPool.PROPERTY_EMPLOYEE_STONE_RECRUIT_COUNT),//抽10次
		STONE_BASE(0, PlayerPool.PROPERTY_EMPLOYEE_STONE_RECRUIT_COUNT),//保底掉落
		STONE_TEN_BADLUCK(0, PlayerPool.PROPERTY_EMPLOYEE_STONE_RECRUIT_COUNT),//抽10次防脸红掉落
		
		MONEY_FREE(0, PlayerPool.PROPERTY_EMPLOYEE_MONEY_RECRUIT_COUNT),//免费
		MONEY_ONE(0, PlayerPool.PROPERTY_EMPLOYEE_MONEY_RECRUIT_COUNT),//抽一次
		MONEY_TEN(0, PlayerPool.PROPERTY_EMPLOYEE_MONEY_RECRUIT_COUNT),//抽10次
		MONEY_HUNDRED(0, PlayerPool.PROPERTY_EMPLOYEE_MONEY_RECRUIT_COUNT),//抽百次...
		MONEY_BASE(0, PlayerPool.PROPERTY_EMPLOYEE_MONEY_RECRUIT_COUNT),//保底掉落
		
		SENIOR_RESUME(30083, PlayerPool.PROPERTY_EMPLOYEE_SENIOR_RESUME_RECRUIT_COUNT),//高级简历产出
		SENIOR_RESUME_BASE(0, PlayerPool.PROPERTY_EMPLOYEE_SENIOR_RESUME_RECRUIT_COUNT),//高级简历保底
		
		GENERAL_RESUME(30082, PlayerPool.PROPERTY_EMPLOYEE_GENERAL_RESUME_RECRUIT_COUNT),//普通简历产出
		GENERAL_RESUME_BASE(0, PlayerPool.PROPERTY_EMPLOYEE_GENERAL_RESUME_RECRUIT_COUNT)//普通简历保底
//		STONE(230, PlayerPool.PROPERTY_EMPLOYEE_STONE_RECRUIT_COUNT), // 钻石招聘
//		SENIOR_RESUME(30083, PlayerPool.PROPERTY_EMPLOYEE_SENIOR_RESUME_RECRUIT_COUNT), // 高级简历
//		GENERAL_RESUME(30082, PlayerPool.PROPERTY_EMPLOYEE_GENERAL_RESUME_RECRUIT_COUNT) // 普通简历
		;
		public final int val; // 物品id
		public final String poolKey;
		Type(int val, String poolKey) {
			this.val = val;
			this.poolKey = poolKey;
		}
		static Type[] vals = values();
		public static Type forCode(int c) {
			return c >= 0 && c < vals.length ? vals[c] : null;
		}
	}

	@Deprecated
	static class Configuration implements Interval {
		protected EmployeeTemplate template;
		protected int weightFrom, weightTo;
		protected Configuration(EmployeeTemplate template, int weightFrom, int weightTo) {
			this.template = template;
			this.weightFrom = weightFrom;
			this.weightTo = weightTo;
		}
		@Override
		public int getMinVal() {
			return weightFrom;
		}
		@Override
		public int getMaxVal() {
			return weightTo;
		}
	}
	
	public static class ConfigurationDropItem implements Interval{
		protected RecruitDropItem dropItem;
		protected int weightFrom, weightTo;
		protected ConfigurationDropItem(RecruitDropItem item, int weightFrom, int weightTo){
			this.dropItem = item;
			this.weightFrom = weightFrom;
			this.weightTo = weightTo;
		}
		@Override
		public int getMinVal() {
			return weightFrom;
		}

		@Override
		public int getMaxVal() {
			return weightTo;
		}
	}
	
	static class RecruitDropItem{
		protected EmployeeProduceV2Template temp;
		protected byte type;
		protected int weight;
		protected RecruitDropItem(EmployeeProduceV2Template temp, int index){
			this.temp = temp;
			this.type = (byte) index;
			this.weight = index > -1 && index < temp.getWeights().length? temp.getWeights()[index]: 0;
		}
		public EmployeeProduceV2Template getTemp(){
			return temp;
		}
	}
	
	
	
	public static class EmployeeRecruitResult{
		public int itemId;
		public int itemCount;
		public int employeeTempId = 0;
		public EmployeeRecruitResult(int itemId, int itemCount){
			this.itemId = itemId;
			this.itemCount = itemCount;
			if(this.itemId > 0){
				ItemTemplate itemtemp = App.getApp().getServiceManager().get(TemplateService.class).get(ItemTemplate.class, itemId);
				if(itemtemp != null){
					if(itemtemp.getEffect() == ItemEffect.ADD_EMPLOYEE){
						employeeTempId = itemtemp.getParameter(0, 0);
					}
				}
			}
		}
		
		public void reputItemId(RecruitListener listener){
			if(this.itemId > 0){
				ItemTemplate itemtemp = App.getApp().getServiceManager().get(TemplateService.class).get(ItemTemplate.class, itemId);
				if(itemtemp != null){
					if(itemtemp.getEffect() == ItemEffect.GET_DROP_GROUP_ITEM){
						this.itemId = listener.itemId;
						this.itemCount = listener.itemCount;
						if(this.itemId > 0){
							ItemTemplate temp = App.getApp().getServiceManager().get(TemplateService.class).get(ItemTemplate.class, itemId);
							if(temp != null){
								if(temp.getEffect() == ItemEffect.ADD_EMPLOYEE){
									employeeTempId = temp.getParameter(0, 0);
								}
							}
						}
					}
				}
			}
		}
	}

	public static class RecruitDropListener implements ItemDropListener{
		private EmployeeRecruitResult result = null;
		@Override
		public void itemDroped(Player player, int itemId, int count) {
			result = new EmployeeRecruitResult(itemId, count);
		}		
		public EmployeeRecruitResult getResult() {
			return result;
		}
	}
	
	public static class RecruitListener implements ItemDropListener{
		int itemId;
		int itemCount;
		@Override
		public void itemAdded(ItemTemplate item, int count) {
			this.itemId = item.getId();
			this.itemCount = count;
		}

		@Override
		public void itemRemoved(ItemTemplate item, int count) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void itemDroped(Player player, int itemId, int count) {
			this.itemId = itemId;
			this.itemCount = count;			
		}
	}
	public List<Integer> getShowGoldProduce() {
		return showGoldProduce;
	}

	public List<Integer> getShowStoneProduce() {
		return showStoneProduce;
	}

	public List<Integer> getShowBookProcue() {
		return showBookProcue;
	}
	
	public int tryGetNextFixDrop(int currentCount){
		int ret = -1;
		for(int i = stoneFixedDropList.size() - 1; i > -1; i--){
			int fixcount = stoneFixedDropList.get(i);
			if(currentCount >= fixcount){
				break;
			}else{
				ret = fixcount - currentCount;
			}
		}
		return ret;
	}

	public EmployeeRecruitConfigure(Configure parent) {
		super(parent);
		random = EmployeeService.RND;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public EmployeeRecruitConfigure configure() {
		List<EmployeeProduceV2Template> templates = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(EmployeeProduceV2Template.class);
		int size = templates.size();
		this.configs = new List[] {
				new ArrayList<Configuration>(size), // 钻石
				new ArrayList<Configuration>(size), // 高级
				new ArrayList<Configuration>(size), // 普通
		};
		for (int i = 0; i < size; i++) {
			EmployeeProduceV2Template template = templates.get(i);
			EmployeeTemplate employeeTemplate = App.getApp().getServiceManager().get(TemplateService.class).get(EmployeeTemplate.class, template.getId()); // employee template
			int[] weights = template.getWeights(); // length=3
			for (int j = 0; j < 3; j++) {
				if (weights[j] > 0) {
					List<Configuration> list = this.configs[j];
					int weightFrom = list.isEmpty() ? 0 : list.get(list.size() - 1).weightTo;
					int weightTo = weightFrom + weights[j];
					Configuration config = new Configuration(employeeTemplate, weightFrom, weightTo);
					list.add(config);
				}
			}
		}
		
		this.itemConfigs = new List[]{
			new ArrayList<RecruitDropItem>(size),//钻石免费
			new ArrayList<RecruitDropItem>(size),//钻石1
			new ArrayList<RecruitDropItem>(size),//钻石10
			new ArrayList<RecruitDropItem>(size),//钻石保底
			new ArrayList<RecruitDropItem>(size),//钻石10防脸红
			new ArrayList<RecruitDropItem>(size),//金币免费
			new ArrayList<RecruitDropItem>(size),//金币1
			new ArrayList<RecruitDropItem>(size),//金币10
			new ArrayList<RecruitDropItem>(size),//金币100
			new ArrayList<RecruitDropItem>(size),//金币保底
			new ArrayList<RecruitDropItem>(size),//高级招聘
			new ArrayList<RecruitDropItem>(size),//高级招聘保底
			new ArrayList<RecruitDropItem>(size),//普通招聘
			new ArrayList<RecruitDropItem>(size),//普通招聘保底
		};
		int count = 0;
		TIntObjectMap<Integer> count2index = new TIntObjectHashMap<>(16);
		countLimitList = new ArrayList<Integer>();
		for(int i = 0; i < size; i++){
			EmployeeProduceV2Template template = templates.get(i);
			int[] weights = template.getWeights(); // length=3
			for(int j = 0; j < 13; j++){
				if(weights[j] > 0){
					List<RecruitDropItem> list = this.itemConfigs[j];
					RecruitDropItem item = new RecruitDropItem(template, j);
					list.add(item);
				}
			}
			count = template.getCountLimit();
			if(!count2index.containsKey(count)){
				countLimitList.add(count);
				count2index.put(count, 1);
			}
		}
		
		countLimitList.sort(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o1 - o2;
			}
		});
		
		fixedDrops = App.getApp().getServiceManager().get(TemplateService.class).getTemplates(EmployeeRecruitFixedDropTemplate.class);
		
		showGoldProduce = new ArrayList<Integer>();
		showStoneProduce = new ArrayList<Integer>();
		showBookProcue = new ArrayList<Integer>();
		List<EmployeeRecruiteShowTemplate> showTempList = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(EmployeeRecruiteShowTemplate.class);
		size = showTempList.size();
		for(int i = 0; i < size; i++){
			EmployeeRecruiteShowTemplate temp = showTempList.get(i);
			if(temp.getGold() > 0){
				showGoldProduce.add(temp.getId());
			}
			if(temp.getStone() > 0){
				showStoneProduce.add(temp.getId());
			}
			if(temp.getBook() > 0){
				showBookProcue.add(temp.getId());
			}
		}
		
		stoneFixedDropList.clear();
		List<EmployeeRecruitFixedDropTemplate> dropList = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(EmployeeRecruitFixedDropTemplate.class);
		for(int i = 0, len = dropList.size(); i < len; i++){
			EmployeeRecruitFixedDropTemplate temp = dropList.get(i);
			if(temp.getStoneId() > 0){
				stoneFixedDropList.add(temp.getId());
			}
		}
		return this;
	}

	@Deprecated
	/**
	 * 招聘一个员工
	 * @param type
	 * @param player
	 * @return
	 */
	public Employee doRecruit(Type type, Player player, EmployeeServiceConfigure refer) {
		player.poolAdd(type.poolKey, 1);
		EmployeeTemplate template = tryFixedDrop(type, player);
		if (template == null) {
			List<Configuration> list = configs[type.ordinal()];
			int maxWeight = list.get(list.size() - 1).getMaxVal();
			int weight = random.nextInt(maxWeight);
			Configuration found = CommonUtils.findInterval(list, weight);
			template = found.template;
		}
		return new Employee(template, player.getEmployees(), refer);
	}
	
	@Deprecated
	private EmployeeTemplate tryFixedDrop(Type type, Player player) {
		int n = player.getPool().getIntValue(type.poolKey);
		EmployeeRecruitFixedDropTemplate t = fixedDrops.get(n);
		return t != null ? t.getEmployeeTemplate(type) : null;
	}
	
	public EmployeeRecruitResult tryFixedDropGroup(Player player, int count, int recruitType){
		EmployeeRecruitResult result = null;
		EmployeeRecruitFixedDropTemplate t = fixedDrops.get(count);
		if(t != null){
			DropGroupTemplate dropTemp = t.getDropGroupTemplate(recruitType);
			if(dropTemp != null){
				DropGroup dropGrop = dropTemp.getDrop();
				RecruitDropListener listener = new RecruitDropListener();
				dropGrop.drop(Drop.RND, player, Cause.EMPLOYEE_RECRUIT, listener);
				result = listener.result;
			}
		}
		return result;
	}
	
	public List<Integer> getCountLimitList() {
		return countLimitList;
	}
	
	public EmployeeRecruitResult doRecruitSingle(Type dropType, Player player, EmployeeServiceConfigure refer, List<ConfigurationDropItem> lastConfigList, int currentCount){
		if(lastConfigList.size() == 0){
			List<RecruitDropItem> list = itemConfigs[dropType.ordinal()];
			int size = list.size();
			int total = 0;
			for(int i = 0; i < size; i++){
				RecruitDropItem item = list.get(i);
				if(player.getLevel() >= item.getTemp().getLevelLimit() && currentCount >= item.getTemp().getCountLimit()){
					int min = total;
					total = total + item.weight;
					lastConfigList.add(new ConfigurationDropItem(item, min, total));
				}
			}
		}
		int maxWeight = lastConfigList.get(lastConfigList.size() - 1).getMaxVal();
		int weight = random.nextInt(maxWeight);
		
		ConfigurationDropItem config = CommonUtils.findInterval(lastConfigList, weight);
		EmployeeRecruitResult result = new EmployeeRecruitResult(config.dropItem.getTemp().getItemId(), config.dropItem.getTemp().getItemCount());
		return result;
	}
}
